package ca.etsmtl.log210.vues;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * 
 * TODO - referer notre travail du cours inf111 au cursus
 *
 */
public class DateChooser extends JDialog{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private final String[] TAB_JOUR_SEMAINE = new String[]					//Les jours de la semaine
	                                                     {"Dim","Lun","Mar","Mer","Jeu","Ven","Sam"};

	private final int[] TAB_NB_JOUR_MAX_PAR_MOIS = new int[] 
	                                                       {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};	//Le nombre de jours pour chacun des mois

	private final String[] TAB_MOIS = new String[]{"Janvier","Fevrier",		//Les mois de l'annee
			"Mars","Avril","Juin","Juillet",
			"Aout","Septembre","Octobre","Novembre","Decembre"};

	private int NB_COLONNE= TAB_JOUR_SEMAINE.length; 	//Nombre de colonnes du calendrier
	private int NB_LIGNE = 7;							//Nombre de jours du calendrier

	private int LARGEUR = 400;	//Largeur de la fenetre
	private int HAUTEUR = 400; 	//Hauteur de la fenetre

	private int annee;			//L'annee selectionnee
	private int mois;			//Le mois selectionne
	private int jour;			//Le jour selectionne

	private final int ANNEE_MIN = 1999;			//La plus petite annee affichee
	private final int NB_ANNEES = 101;			//Le nombre d'annees a afficher

	Calendar calendrier;						//Un objet Calendar pour associer les jours, les mois, et les annees

	PanneauComboMoisAnnee panneauComboMoisAnnee;//Le panneau pour le choix du mois et de l'annee
	PanneauJour panneauJour;					//Le panneau avec la grille des jours

	/**
	 * Permet de sélectionner une date et de l'obtenir en String 
	 * dans le format dd/mm/aaaa
	 */
	public DateChooser(){

		//Sert à obtenir la date de l'ordi
		calendrier = Calendar.getInstance();

		//Au départ, on initialise les attributs à la date du jour
		annee = calendrier.get(Calendar.YEAR);
		mois = calendrier.get(Calendar.MONTH);
		jour = calendrier.get(Calendar.DAY_OF_MONTH);

		//On affiche les jours selon le moisJOptionPane.showInputDialog dans ce panneau
		panneauJour = new PanneauJour();

		//Création du panneau permettant de sélectionner le mois et l'année
		panneauComboMoisAnnee = new PanneauComboMoisAnnee();

		//Fenêtre modale
		setModalityType(JDialog.DEFAULT_MODALITY_TYPE);

		//évite pls appels à getContentPane
		JPanel p = (JPanel)getContentPane();

		//ajout des composants dans le panneau de la fenêtre
		p.add(panneauComboMoisAnnee,BorderLayout.NORTH);
		p.add(panneauJour);
		
		JButton boutonConfirm = new JButton("Confirm");
		boutonConfirm.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				//TODO
				dispose();
			}
		});
		
		p.add(boutonConfirm, BorderLayout.SOUTH);

		//dimension de la fenêtre
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();

		//Vous pouvez mettre les valeurs qui vous tentent pour ces constantes
		setSize(LARGEUR,HAUTEUR);

		//Position au centre de l’écran
		setLocation((d.width-LARGEUR)/2,(d.height-HAUTEUR)/2);
		setResizable(false);

		//On ne ferme pas l’application.  On enlève la fenêtre de la mémoire sur X
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

	}

	/**
	 * Retourne la date sélectionnée en String
	 * @param msgSollicitation Le message à afficher dans la zone de titre
	 * @return  La date choisie en String
	 */
	public Date getDate(String msgSollicitation){

		setTitle(msgSollicitation); //On met le titre demande
		setVisible(true); //On rend la fenetre visible
		return new Date((annee-1900), (mois+1), jour); //On retourne la date choisie
	}


	/**
	 * Gere l'affichage et la gestion du panneau de la grille des jours
	 * @author yohan
	 *
	 */
	public class PanneauJour extends JPanel{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		private static final int PREMIER_JOUR_MOIS = 1;	//Le premier jour du mois (vaut 1 pour tous les mois)
		JButton boutJour[];								//Le tableau de boutons pour la grille

		/**
		 * Constructeur
		 */
		public PanneauJour() {

			//On set un layout en grille avec un nombre donne de lignes et de colonnes
			setLayout(new GridLayout(NB_LIGNE, NB_COLONNE));

			//Affichage des composants
			paintComponent();
		}

		/**
		 * Responsable de l'affichage de la grille
		 */
		public void paintComponent(){

			//On enleve tout ses composants avant de les reajouter
			removeAll();

			//Ajout des noms des jours de semaine
			for(int jour = 0; jour < NB_COLONNE; jour++){
				add(new CaseWeekday("" + TAB_JOUR_SEMAINE[jour]));
			}

			//Mettre une instance de calendrier au premier jour du mois et de l'annee donnee
			Calendar cal = Calendar.getInstance();
			cal.set(annee, mois, PREMIER_JOUR_MOIS);

			//Determiner le jour de la semaine qui debute le mois
			int premierJour = cal.get(Calendar.DAY_OF_WEEK);

			//Ajouter des cases vides au debut, avant le premier jour
			for(int i = 1; i < premierJour; i++)
				add(new CaseVide());

			//Determiner le nombre de jours dans le mois
			int dernierJour = TAB_NB_JOUR_MAX_PAR_MOIS[mois];

			//Creation du tableau
			boutJour = new JButton[dernierJour];

			//Ajout des boutons des jours du mois et des ecouteurs
			for(int jour = 0; jour < dernierJour; jour++){

				boutJour[jour] = new CaseChiffre(jour+1); //Affichage du chiffre dans la case

				add(boutJour[jour]); //ajout au panneau

				boutJour[jour].addActionListener(new ecouteurJours(TAB_NB_JOUR_MAX_PAR_MOIS[mois])); //Ajout de l'ecouteur
			}

			//Ajout de cases vides a la fin (en recherchant combien de cases sont encore a remplir)
			int nbCasesManquantes = NB_COLONNE * NB_LIGNE - dernierJour - premierJour - TAB_JOUR_SEMAINE.length +1;
			for(int i = 0; i < nbCasesManquantes; i++)
				add(new CaseVide());

			//Aviser des modifications
			validate();
		}

		/**
		 * Marquer un jour comme selectionne
		 * @param jourChoisi Le jour a selectionner
		 */
		public void setJourSelected(int jourChoisi){
			jour = jourChoisi;  //Mise en memoire du jour dans la variable globale
			paintComponent();	//Reinitialisation de la grille
			boutJour[jour - 1].setBackground(Color.red); //Mise en couleur de la case du jour choisi
		}
	}

	/**
	 * Ecouteur des boutons de la grille
	 * @author yohan
	 *
	 */
	public class ecouteurJours implements ActionListener{

		int nbJours; //Nombre de jours du mois

		/**
		 * Constructeur
		 * @param nbJours Le nombre de jours dans le mois selectionne
		 */
		public ecouteurJours(int nbJours){
			this.nbJours = nbJours;
		}

		@Override
		public void actionPerformed(ActionEvent arg0) {

			//Pour chaque jour du mois, on verifie si le bouton clique est celui de ce jour la
			for(int i = 0; i < nbJours; i++){

				if(arg0.getSource().equals(panneauJour.boutJour[i])){
					panneauJour.setJourSelected(i + 1); //On selectionne le jour

				}

			}
		}
	}


	/**
	 * Ecouteur pour les comboBox
	 * @author yohan
	 *
	 */
	public class ecouteurCombo implements ItemListener{

		@Override
		public void itemStateChanged(ItemEvent e) {

			//Si quelque chose change, on change les variables globales
			mois = panneauComboMoisAnnee.comboMois.getSelectedIndex();
			annee = ANNEE_MIN + panneauComboMoisAnnee.comboAnnee.getSelectedIndex();

			//Et on update la grille
			panneauJour.paintComponent();
		}
	}

	/**
	 * Panneau avec les ComboBox des jours et des mois
	 * @author yohan
	 *
	 */
	public class PanneauComboMoisAnnee extends JPanel{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		JComboBox comboAnnee; 	//Pour l'Annee
		JComboBox comboMois;	//Pour le mois

		/**
		 * Constructeur
		 */
		public PanneauComboMoisAnnee() {

			String listeAnnee[] = new String[NB_ANNEES];	//Liste de toutes les annees a utiliser

			//Tant qu'il reste des annees, on les met dans la liste
			for(int item = 0; item < NB_ANNEES; item++)	
				listeAnnee[item] = "" + (item + ANNEE_MIN);

			//On remplit les deux combo Box
			comboAnnee = new JComboBox(listeAnnee);
			comboAnnee.setSelectedIndex(annee - ANNEE_MIN);

			comboMois = new JComboBox(TAB_MOIS);
			comboMois.setSelectedIndex(mois);

			//On ajoute les comboBox au panneau
			add(comboMois);
			add(comboAnnee);

			//On ajoute les ecouteurs
			comboMois.addItemListener(new ecouteurCombo());
			comboAnnee.addItemListener(new ecouteurCombo());
		}
	}

	/**
	 * JButton pour une case vide
	 * @author yohan
	 *
	 */
	public class CaseVide extends JButton{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public CaseVide(){
			//BG blanc
			setBackground(Color.white);

		}
	}

	/**
	 * JButton pour une case avec un chiffre
	 * @author yohan
	 *
	 */
	public class CaseChiffre extends CaseVide{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public CaseChiffre(int chiffre){

			//On ajoute le chiffre
			setText("" + chiffre);

		}
	}

	/**
	 * JLabel pour une case de nom de jour
	 * @author yohan
	 *
	 */
	public class CaseWeekday extends JLabel{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public CaseWeekday(String jour){

			//On met l'arriere-plan gris
			setOpaque(true);
			setBackground(Color.lightGray);

			//On met le texte demande
			setText(jour);

			//On centre le texte
			setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

		}
	}

}
